﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using eProject.Model;

namespace eProject.ViewModel
{
    public class ActivityViewModel : ViewModelBase
    {        

        #region Constructor

        internal ActivityViewModel(CommonManager manager, TaskViewModel taskViewModel, EmployeeViewModel employeeViewModel, Activity activity)
        {
            if (manager == null) throw new ArgumentNullException("manager");
            if (activity == null) throw new ArgumentNullException("activity");     
            if (taskViewModel == null) throw new ArgumentNullException("taskViewModel");
            if (employeeViewModel == null) throw new ArgumentNullException("employeeViewModel");

            _manager = manager;
            Activity = activity;
            Task = taskViewModel;
            Employee = employeeViewModel;

            _details = new ObservableCollection<ActivityDetailizationViewModel>();
            _roDetails = new ReadOnlyObservableCollection<ActivityDetailizationViewModel>(_details);
            RefreshDetails();

            _manager.ManHoursChanged += OnManHoursChanged;
            IsUnlinked = false;
        }        

        #endregion

        #region Properties

        internal Activity Activity { get; private set; }

        public TaskViewModel Task { get; private set; }

        public EmployeeViewModel Employee { get; private set; }
        
        public Period Period
        {
            get { return Activity.Period; }
            set
            {//TODO Activity.Period maybe null??                
                if (Activity.Period.Equals(value)) return;
                Activity.Period = value;
                InvokePropertyChanged("Period");
            }
        }
        
        public int Priority
        {
            get { return Activity.Priority; }
            set
            {
                if (Activity.Priority == value) return;
                Activity.Priority = value;
                InvokePropertyChanged("Priority");
            }
        }

        public double ManHours { get { return _manager.GetManHours(this); } }

        public ReadOnlyObservableCollection<ActivityDetailizationViewModel> Details { get { return _roDetails; } }

        public string Description
        {
            get { return Activity.Description; }
            set
            {
                if (Description == value) return;
                Activity.Description = value;
                InvokePropertyChanged("Description");
            }
        }

        public bool IsUnlinked { get; private set; }

        #endregion

        #region Private Section

        private readonly CommonManager _manager;
        private readonly ObservableCollection<ActivityDetailizationViewModel> _details;
        private readonly ReadOnlyObservableCollection<ActivityDetailizationViewModel> _roDetails;
        

        private void OnManHoursChanged(IEnumerable<Activity> activities)
        {
            if (activities.Contains(Activity))
            {
                RefreshDetails();
                InvokePropertyChanged("ManHours");                
            }
        }

        private void RefreshDetails()
        {
            //_details.Clear();
            var details = _manager.GetDetails(this);
            var delta = _details.Count - details.Count();
            if (delta > 0)
            {
                for (int i = _details.Count - 1, n=_details.Count; i >= n - delta; i--)
                {
                    _details.RemoveAt(i);
                }
            }
            else if (delta < 0)
            {
                for (var i = 0; i < -delta; i++)
                {
                    _details.Add(new ActivityDetailizationViewModel(this));
                }
            }
            var dt = Period.Begin.Date;
            var j = 0;
            foreach (var item in details)
            {
                _details[j].Date = dt;
                _details[j].ManHours = item;
                j++;
                dt = dt.AddDays(1);
            }
        }
    

        #endregion

        #region Methods

        public void Unlink()
        {
            if (IsUnlinked) return;
            _manager.ManHoursChanged -= OnManHoursChanged;
            IsUnlinked = true;
        }
        #endregion
    }
}
